Conversation
Add .github/workflows/publish.yml: on push to main, run the check matrix (check/smoke/pack:check on Node 18/20/22), then publish to npm via OIDC Trusted Publishing with no stored NPM_TOKEN. Publish-on-version-change: package.json version is the source of truth and the publish step only runs when that version is not yet on npm. Publish job requires id-token: write and is gated behind a release environment. Workflow file only; first publish + npm Trusted Publisher config left to a human.
A [goal:complete] is now only archived when accompanied by a non-empty [goal:evidence] line, and a [goal:blocked] only stops the goal when a concrete blocker is stated. Unsubstantiated claims are rejected and the plugin re-prompts for the missing evidence/blocker via a new <evidence_required> continuation block. Evidence is stored on the result and surfaced in /goal status and /goal history. Adds extractCompletionEvidence, threads evidence through result persistence, updates continuation/system/compaction/creation prompts and the README, and adds unit + handler tests. Implements megalist item 2.1.
Add a no-tool-call gate complementing the low-output no-progress check: track continuation turns whose assistant message has no tool/subtask parts, and pause with reason "no tool calls" after noToolCallTurnsBeforePause consecutive tool-free turns (default 2). Guards against self-chat loops. Configurable via the noToolCallTurnsBeforePause option and --no-tool-turns flag; counter is persisted and reset by /goal resume. Adds messageHasToolCall, threads the counter through state/persistence, updates the README, and adds unit + handler tests. Item 5.1.
Detect a genuine human message that arrives after the plugin's most recent continuation prompt and pause the goal (stop reason "user intervention") so the plugin does not talk over the user; resume via /goal resume. Plugin-generated continuation prompts (user-role messages framed in <goal_continuation>) are ignored, and detection requires turnCount > 0 plus a visible plugin continuation so the first idle and scrolled-out sessions are never misread. Adds isPluginContinuationMessage and userInterventionDetected helpers, the idle-handler check, README/CHANGELOG, and unit + handler tests. Implements items 5.2 and 5.3.
Goals can now carry successCriteria (--success), constraints/non-goals (--constraints/--non-goals), and a mode of normal or ordered (--mode, sisyphus alias). parseGoalArguments gains string/enum flag support and a meta object; fields thread through state, persistence, the injected goal block (escaped, new success_criteria/constraints structural tags), creation output, and /goal status. Ordered mode adds a strict-sequence instruction. Adds normalizeMode plus unit/parsing/command tests. Items 4.1, 4.2, 4.3.
Resolve the state-file path as stateFilePath option > OPENCODE_GOAL_STATE_PATH env var > project-local <cwd>/.opencode/goals/state.json (previously the home-dir default). When the default path is empty, migrate forward on first load from the legacy ~/.opencode-goal-plugin path and the XDG state path, then persist to the project-local path. Explicit option/env paths are literal with no fallback, and a corrupt primary file is preserved. Refactors the loader into applyParsedStateFile + a candidate loop, adds resolveStateFilePath/xdgStateFilePath/legacyStateFilePaths, README/CHANGELOG, and unit + migration tests. Items 6.1 and 6.2.
Add a --budget shorthand for the context-token limit (--max-tokens) that accepts a plain integer or a k/m suffix, e.g. --budget 100k == 100000. New parseTokenBudget helper and a tokens flag type in parseGoalArguments; invalid values are rejected with a clear error. README/CHANGELOG and unit + parsing tests. Item 8.1.
Add a commandName plugin option (default goal, leading slash tolerated) so the plugin can own e.g. /objective, with all user-facing hints following the configured name, and a registerCommand:false option that omits the command hook entirely for programmatic-only setups. Adds normalizeCommandOptions, parameterizes the /goal hint strings, and adds unit + command-hook tests. Item 8.2.
…d terminal persistence Emit every lifecycle event to an append-only JSONL ledger (<stateFile>.ledger.jsonl, 0600) carrying the objective, so state can be reconstructed when the main state file is missing. loadPersistedState recovers still-active goals from the ledger (new 'reconstructed' status) and reloads them paused. persistState now returns success/failure; terminal (complete/blocked) transitions write the ledger event before the state write and log on failure, so a terminal outcome survives a failed state write (fail-closed). Ledger is tied to persistState. Adds appendLedgerLine/readLedgerEntries/reconstructGoalsFromLedger plus unit and end-to-end recovery tests. Items 2.3 and 2.5.
When the assistant marks a goal complete or blocked, emit an audit-start and an audit-result message instead of acting silently. Delivery defaults to client.app.log (visible, non-disruptive) and is pluggable via an auditMessenger option or disable-able with auditMessages:false. Adds defaultAuditMessenger plus handler and unit tests. Item 2.4.
buildCompactionContext now folds in a reproducible progress summary (recent checkpoints + recent lifecycle events) reconstructed from the goal's persisted checkpoints/history via a new buildCompactionProgressSummary helper, instead of relying on chat memory, and labels it as such. Adds unit tests for windowing, determinism, the empty case, and inclusion in the compaction context. Item 6.3.
Add a sessionGoals registry so a session can hold several live goals, keeping goalStates as the focused-goal mirror the idle handler drives. /goal <cond> replaces the focused goal; /goal add backgrounds it and focuses a new one (only the focused goal auto-continues). /goal list shows numbered live goals plus a per-session archive of completed goals; /goal focus <n|id> switches the active goal. A numeric focus ref is treated strictly as a 1-based index (never a goalId prefix) so it can't spuriously match a UUID. Focus is tracked per session and persisted (state gains a per-goal focused flag and an archives array; older single-goal files load with their goal focused). Adds buildGoalState/formatGoalList/registry helpers and command + persistence round-trip tests. Items 3.1, 3.2, 3.3.
Add /goal sisyphus <obj1>; <obj2>; ... to set up a strict execution sequence: the first objective is focused and the rest queued, and the plugin auto-promotes the next goal to focus when the focused one completes, until the sequence is exhausted. The ordered flag is tracked per session, shown in /goal list, persisted (orderedSessions), and cleared by /goal clear. Adds promoteNextOrderedGoal plus command, auto-promotion, and persistence tests. Builds on multi-goal. Item 3.4.
When a completion auditor is configured, a [goal:complete] is verified before the goal is archived: approval archives as achieved; rejection restores the goal (pauses it with reason 'audit rejected') instead of archiving. Enable the built-in child-session auditor with completionAudit:true, or supply a custom auditor function (takes precedence). Built-in fails open without the session API; a thrown custom auditor or ambiguous verdict fails closed. Off by default. Adds parseAuditVerdict/buildAuditPrompt/createChildSessionAuditor plus verdict-parsing, orchestration, and child-session-wiring tests. Item 2.2.
# Conflicts: # src/goal-plugin.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
# Conflicts: # src/goal-plugin.js # test/goal-plugin.test.js
Consolidate the Unreleased changelog into a 0.3.0 section and bump package.json to 0.3.0. Integrates the full megalist work: completion evidence gate + optional auditor + visible audit messages, lifecycle ledger with reconstruction and fail-closed terminal persistence, multi-goal management + sisyphus ordered sequences, richer goal schema, no-tool-call + user-intervention guardrails, project-local state with migration, agent-facing tools, deterministic compaction summary, and npm Trusted Publishing CI.
…form parity os.homedir() ignores $HOME on macOS, so the XDG-migration test's HOME override did not isolate the legacy ~/.opencode-goal-plugin fallback and collided with a real user state file. Resolve the home base from an injectable env.HOME (falling back to os.homedir()), thread env/cwd through GoalPlugin, and make the migration test inject config instead of mutating process globals. No production behavior change where env.HOME == real home.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v0.3.0 — Goal Mode upgrades (megalist Phases 1–3)
Implements the improvements tracked in the v0.3.0 megalist. Everything is additive and backward-compatible — older
state.jsonfiles load unchanged, and every new behavior is off-by-default or preserves the prior default.What changed
Completion integrity & audit
[goal:evidence]line to accept[goal:complete], and a concrete blocker to accept[goal:blocked]; unsubstantiated claims are rejected and re-prompted (2.1).completionAudit: trueor a customauditor(2.2). Off by default.auditMessenger, disable withauditMessages: false(2.4).Durability
<stateFile>.ledger.jsonl) with state reconstruction when the main state file is missing, and fail-closed terminal-state persistence (2.3, 2.5).Auto-continue guardrails
--no-tool-turns) (5.1).Multiple goals
/goal add,/goal list,/goal focusand per-session focus tracking (3.1, 3.2, 3.3)./goal sisyphusordered sequences that auto-promote the next goal on completion (3.4).Schema & command UX
successCriteria/constraints/modegoal fields via--success/--constraints/--mode(4.1–4.3).--budget <n>(k/m suffixes) shorthand for the token limit (8.1).commandNameandregisterCommandtoggle (8.2).Storage, tools & packaging
<cwd>/.opencode/goals/state.json) +OPENCODE_GOAL_STATE_PATHenv override + migration from legacy/XDG paths (6.1, 6.2).get_goal/get_goal_history/set_goal/update_goal/clear_goalvia the optional@opencode-ai/pluginpeer dependency, loaded by dynamic import (7.1, 7.2).PublishGitHub Actions workflow for npm Trusted Publishing (OIDC), publish-on-version-change (9.1).See
CHANGELOG.md(## 0.3.0) for the per-item detail.Why
These close the largest gaps versus the upstream Goal Mode PRD and the prevalentWare/watzon implementations: completion couldn't be trusted (no evidence/audit), state wasn't durable beyond a single JSON file, only one goal per session was possible, and there was no automated release path. The changes harden unattended runs and make the plugin's release process reproducible.
Checks run
npm run check→ 138 tests pass (was 83); 0 failures across 10 repeated runs.npm run smoke→ passes (tool registration / ledger / audit all degrade gracefully underpersistState:false).npm run pack:check→ buildsopencode-goal-plugin-0.3.0.tgz; package contents unchanged.-csyntax check clean; no conflict markers.Manual OpenCode smoke testing
Not yet performed against a live OpenCode for the new hooks. Recommended before relying on these unattended, and called out in the notes:
ctx.sessionID/tool.schemashapes and the built-in completion auditor's child-session wiring are taken from OpenCode docs, not a live run;client.app.logpending a confirmed non-prompting conversation-message API;Notes for reviewers
@opencode-ai/plugin(dynamic import; absence is handled).focusedflags,archives, andorderedSessions— additive; older single-goal files still load.